/* Kernel includes. */
#include "GpioPort.h"
#include "FreeRTOS.h"
#include "timers.h"
#include "Mpu.h"
#include "Adc.h"
#include "Dma.h"
#include "TLE94112.h"
#include "TLE75008.h"
#include "AdcDeal.h"
#include "WDG.h"
#include "com.h"
#include "CAN.h"


/* Priorities at which the tasks are created. */
#define BSWTask_1ms_PRIORITY (tskIDLE_PRIORITY + 5)
#define BSWTask_2ms_PRIORITY (tskIDLE_PRIORITY + 4)
#define BSWTask_5ms_PRIORITY (tskIDLE_PRIORITY + 3)
#define BSWTask_10ms_PRIORITY (tskIDLE_PRIORITY + 2)

#define ASWTask_1ms_PRIORITY (tskIDLE_PRIORITY + 10)
#define ASWTask_2ms_PRIORITY (tskIDLE_PRIORITY + 9)
#define ASWTask_5ms_PRIORITY (tskIDLE_PRIORITY + 8)
#define ASWTask_10ms_PRIORITY (tskIDLE_PRIORITY + 7)

#define ASWTask_1s_PRIORITY (tskIDLE_PRIORITY + 1)

/* The rate at which data is sent to the queue, specified in milliseconds, and
converted to ticks using the portTICK_PERIOD_MS constant. */
#define TASK_DELAY_1MS (1UL / portTICK_PERIOD_MS)
#define TASK_DELAY_2MS (2UL / portTICK_PERIOD_MS)
#define TASK_DELAY_5MS (5UL / portTICK_PERIOD_MS)
#define TASK_DELAY_10MS (10UL / portTICK_PERIOD_MS)
#define TASK_DELAY_50MS (50UL / portTICK_PERIOD_MS)
#define TASK_DELAY_1S (1000UL / portTICK_PERIOD_MS)

/* A block time of zero simply means "don't block". */
#define mainDONT_BLOCK (0UL)

/*
 * The tasks as described in the comments at the top of this file.
 */
static void BSWTask_1ms(void *pvParameters);
static void BSWTask_2ms(void *pvParameters);
static void BSWTask_5ms(void *pvParameters);
static void BSWTask_10ms(void *pvParameters);

static void ASWTask_1ms(void *pvParameters);
static void ASWTask_2ms(void *pvParameters);
static void ASWTask_5ms(void *pvParameters);
static void ASWTask_10ms(void *pvParameters);

static void ASWTask_1s(void *pvParameters);

uint32_t cntt = 0;
uint32_t Interior_Light_DIAG;

void vApplicationMallocFailedHook( void )
{
    /* Called if a call to pvPortMalloc() fails because there is insufficient
    free memory available in the FreeRTOS heap.  pvPortMalloc() is called
    internally by FreeRTOS API functions that create tasks, queues, software
    timers, and semaphores.  The size of the FreeRTOS heap is set by the
    configTOTAL_HEAP_SIZE configuration constant in FreeRTOSConfig.h. */
    taskDISABLE_INTERRUPTS();
    for( ;; );
}
/*-----------------------------------------------------------*/

void vApplicationStackOverflowHook( TaskHandle_t pxTask, char *pcTaskName )
{
    ( void ) pcTaskName;
    ( void ) pxTask;

    /* Run time stack overflow checking is performed if
    configCHECK_FOR_STACK_OVERFLOW is defined to 1 or 2.  This hook
    function is called if a stack overflow is detected. */
    taskDISABLE_INTERRUPTS();
    for( ;; );
}
/*-----------------------------------------------------------*/

void vApplicationIdleHook( void )
{
    volatile size_t xFreeHeapSpace;

    /* This function is called on each cycle of the idle task.  In this case it
    does nothing useful, other than report the amount of FreeRTOS heap that
    remains unallocated. */
    xFreeHeapSpace = xPortGetFreeHeapSize();

    if( xFreeHeapSpace > 100 )
    {
        /* By now, the kernel has allocated everything it is going to, so
        if there is a lot of heap remaining unallocated then
        the value of configTOTAL_HEAP_SIZE in FreeRTOSConfig.h can be
        reduced accordingly. */
    }

}

/* A tick hook is used by the "Full" build configuration.  The Full and blinky
build configurations share a FreeRTOSConfig.h header file, so this simple build
configuration also has to define a tick hook - even though it does not actually
use it for anything. */
void vApplicationTickHook( void ) {}

/* The queue used by both tasks. */
void FreeRTOS_Start(void)
{
    xTaskCreate( BSWTask_1ms, "BSWTask_1ms", configMINIMAL_STACK_SIZE, NULL, BSWTask_1ms_PRIORITY, NULL);
    xTaskCreate( BSWTask_2ms, "BSWTask_2ms", configMINIMAL_STACK_SIZE, NULL, BSWTask_2ms_PRIORITY, NULL);
    xTaskCreate( BSWTask_5ms, "BSWTask_5ms", configMINIMAL_STACK_SIZE, NULL, BSWTask_5ms_PRIORITY, NULL);
    xTaskCreate( BSWTask_10ms,"BSWTask_10ms",configMINIMAL_STACK_SIZE, NULL, BSWTask_10ms_PRIORITY,NULL);

    xTaskCreate( ASWTask_1ms, "ASWTask_1ms", configMINIMAL_STACK_SIZE, NULL, ASWTask_1ms_PRIORITY, NULL);
    xTaskCreate( ASWTask_2ms, "ASWTask_2ms", configMINIMAL_STACK_SIZE, NULL, ASWTask_2ms_PRIORITY, NULL);
    xTaskCreate( ASWTask_5ms, "ASWTask_5ms", configMINIMAL_STACK_SIZE, NULL, ASWTask_5ms_PRIORITY, NULL);
    xTaskCreate( ASWTask_10ms,"ASWTask_10ms",configMINIMAL_STACK_SIZE, NULL, ASWTask_10ms_PRIORITY,NULL);

    xTaskCreate( ASWTask_1s, "ASWTask_1s", configMINIMAL_STACK_SIZE, NULL, ASWTask_1s_PRIORITY, NULL);

    vTaskStartScheduler();
}

static void BSWTask_1ms( void *pvParameters )
{
    TickType_t xNextWakeTime;
    (void)pvParameters;

    xNextWakeTime = xTaskGetTickCount();
    for( ;; )
    {
        vTaskDelayUntil( &xNextWakeTime, TASK_DELAY_1MS);
        adc_1ms_task();
        GPIOC->PTOR = PORT_PIN_24;// TOGGLE IO_Limphome_Trigger
        GPIOC->PTOR = PORT_PIN_23;//TOGGLE IO_IGN1_Relay_Ctrl_Lock
        /*WDG test*/
//        if(cntt < 10){
//        	WD_task();
//        }
//        WD_task();
    }
}

static void BSWTask_2ms( void *pvParameters )
{
    TickType_t xNextWakeTime;
    /* Casting pvParameters to void because it is unused */
    (void)pvParameters;

    /* Initialise xNextWakeTime - this only needs to be done once. */
    xNextWakeTime = xTaskGetTickCount();

    for( ;; )
    {
        vTaskDelayUntil(&xNextWakeTime, TASK_DELAY_2MS);
    }
}


static void BSWTask_5ms(void *pvParameters)
{
    TickType_t xNextWakeTime;
    /* Casting pvParameters to void because it is unused */
    (void)pvParameters;
    xNextWakeTime = xTaskGetTickCount();
    vTaskDelayUntil(&xNextWakeTime, TASK_DELAY_50MS);
    vTaskDelayUntil(&xNextWakeTime, TASK_DELAY_50MS);
    /* Initialise xNextWakeTime - this only needs to be done once. */
//    TLE94112_Init();

    for( ;; )
    {
        vTaskDelayUntil( &xNextWakeTime, TASK_DELAY_5MS);
//        TLE94112_MainFunction();
        Com_MainFunction();
    }
}


static void BSWTask_10ms(void *pvParameters)
{
    TickType_t xNextWakeTime;
    /* Casting pvParameters to void because it is unused */
    (void)pvParameters;

    /* Initialise xNextWakeTime - this only needs to be done once. */
    xNextWakeTime = xTaskGetTickCount();

    for( ;; )
    {
        vTaskDelayUntil( &xNextWakeTime, TASK_DELAY_10MS );
        // GPIOC->PTOR = IO_IGN1RelayCtrl_PIN;
//        GPIOA->PTOR = PORT_PIN_14;
//        GPIOA->PTOR = PORT_PIN_11;
        Interior_Light_DIAG = IoIf_get_Interior_Light_DIAG();
    }
}

static void ASWTask_1ms( void *pvParameters )
{
    TickType_t xNextWakeTime;
    (void)pvParameters;

    xNextWakeTime = xTaskGetTickCount();
    for( ;; )
    {
        vTaskDelayUntil( &xNextWakeTime, TASK_DELAY_1MS);
    }
    
}

static void ASWTask_2ms( void *pvParameters )
{
    TickType_t xNextWakeTime;
    /* Casting pvParameters to void because it is unused */
    (void)pvParameters;

    /* Initialise xNextWakeTime - this only needs to be done once. */
    xNextWakeTime = xTaskGetTickCount();

    for( ;; )
    {
        vTaskDelayUntil( &xNextWakeTime, TASK_DELAY_2MS );
      
    }
}

static void ASWTask_5ms( void *pvParameters )
{
    TickType_t xNextWakeTime;
    /* Casting pvParameters to void because it is unused */
    (void)pvParameters;

    /* Initialise xNextWakeTime - this only needs to be done once. */
    xNextWakeTime = xTaskGetTickCount();

    for (;;)
    {
        vTaskDelayUntil( &xNextWakeTime, TASK_DELAY_5MS );
    }
}

bool g_bExitFlag = false;
float g_aVoltageBuffer[ADC0_CHN_NUM_EN];
static void ASWTask_10ms( void *pvParameters )
{
    TickType_t xNextWakeTime;
    /* Casting pvParameters to void because it is unused */
    (void)pvParameters;

    /* Initialise xNextWakeTime - this only needs to be done once. */
    xNextWakeTime = xTaskGetTickCount();

    for(;;)
    {
        // Bsp_ADC_Run(g_aVoltageBuffer);
        vTaskDelayUntil( &xNextWakeTime, TASK_DELAY_10MS );
//        BSP_CAN_TransmitData();
    }
}

static void ASWTask_1s( void *pvParameters )
{
    TickType_t xNextWakeTime;
    /* Casting pvParameters to void because it is unused */
    (void)pvParameters;

    /* Initialise xNextWakeTime - this only needs to be done once. */
    xNextWakeTime = xTaskGetTickCount();

    for(;;)
    {
        vTaskDelayUntil(&xNextWakeTime, TASK_DELAY_1S);
//        if(cntt>3){
        	GPIOC->PTOR = PORT_PIN_12;
//        }
//        else{
        	cntt++;
//        }
//        	GPIOA->PTOR = PORT_PIN_2;//WEED
//        	GPIOA->PTOR = PORT_PIN_14;//WD_EN
    }
}
